package com.treasury.glasses.controller;

import com.treasury.glasses.controller.helper.ActiveMenuManager;
import com.treasury.glasses.Main;
import com.treasury.glasses.controller.helper.MaskPath;
import com.treasury.glasses.domain.ActivityLog;
import com.treasury.glasses.domain.fields.ActivityType;
import com.treasury.glasses.domain.ProgramUser;
import com.treasury.glasses.service.SceneService;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.ResourceBundle;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Menu;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;

/**
 * Controller or BackEnd for the FrontEnd Scene mask. Handles the mask
 * functionality and program states.
 * @author <a href="mailto:glasses@audienz.eu">Jean-Luc Burot</a>
 */

public class SceneController implements Initializable {
    /**
     * Privately handled service class for this controller class.
     */
    private final SceneService service;
    
    /**
     * Manager for the activity.
     */
    private ActiveMenuManager activityManager;
    
    /**
     * Link to the activity marked control on the mask.
     */
    @FXML
    private TreeView activity;
    
    /**
     * Link to the container marked control on the mask.
     */
    @FXML
    private BorderPane container;
    
    /**
     * Link to the userMenu marked control on the mask.
     */
    @FXML
    private Menu userMenu;
    
    /**
     * Link to the menuPane marked control on the mask.
     */
    @FXML
    private BorderPane menuPane;
    
    /**
     * Controller for the Scene mask.
     */
    public SceneController() {
        // Instantiations
        this.service = new SceneService();
        
        // Register this controller to Main.
        Main.setSceneController(this);
        
        System.out.println("load constructor SceneController()");
    }
    
    /**
     * Takes the ActionEvent of the close MenuItem on the mask.
     */
    @FXML
    private void closeMenuItemAction() {
        closeProgram();
    }
    
    /**
     * Takes the ActionEvent of the logout MenuItem on the mask.
     */
    @FXML
    private void logoutMenuItemAction() {
        try {
            logout();
        } catch (IOException ex) {
            // TODO
            Logger.getLogger(SceneController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Takes the ActionEvent of the settings MenuItem on the mask.
     */
    @FXML
    private void settingsMenuItemAction() {
        try {
            loadSettings();
        } catch (IOException ex) {
            // TODO
            Logger.getLogger(SceneController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Takes the ActionEvent of the accounting MenuItem on the mask.
     */
    @FXML
    private void accountingMenuItemAction() {
        try {
            loadAccounting();
        } catch (IOException ex) {
            // TODO
            Logger.getLogger(SceneController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Takes the ActionEvent of the about MenuItem on the mask.
     */
    @FXML
    private void aboutMenuItemAction() {
        try {
            loadAbout();
        } catch (IOException ex) {
            // TODO
            Logger.getLogger(SceneController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Takes the ActionEvent of the activity MenuItem on the mask.
     */
    @FXML
    private void activityMenuItemAction() {
        try {
            loadActivity();
        } catch (IOException ex) {
            // TODO
            Logger.getLogger(SceneController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    /**
     * Closes the program.
     */
    private void closeProgram() {
        // Create an ActivityLog.
        createActivityLog(Main.getLoggedInUser(), ActivityType.SYSTEM_STOP);
        
        // Shutdown the Program.
        System.exit(0);
    }
    
    /**
     * Logs out the ProgramUser.
     */
    private void logout() throws IOException {
        // Create an ActivityLog.
        createActivityLog(Main.getLoggedInUser(), ActivityType.USER_LOGOUT);
        
        // Logout the current ProgramUser.
        Main.getLoginController().logoutProgramUser();
        
        // Load the Login mask.
        loadLogin();
    }
    
    /**
     * Loads the Login mask.
     */
    private void loadLogin() throws IOException {
        System.out.println("load SceneController.loadLogin()");
        
        this.container.setTop(null);
        this.container.setLeft(null);
        this.activityManager.setMask(MaskPath.LOGIN);
    }
    
    /**
     * Reloads all the scene settings.
     * @throws IOException
     */
    public final void loadScene() throws IOException {
        this.userMenu.setText(Main.getLoggedInUser().getFirstName() + " " + Main.getLoggedInUser().getLastName());
        this.container.setTop(this.menuPane);
        this.container.setLeft(this.activity);
        this.activityManager.delMask(MaskPath.LOGIN);
    }
    
    /**
     * Loads the Settings mask.
     * @throws IOException
     */
    public final void loadSettings() throws IOException {
        this.activityManager.setMask(MaskPath.SETTINGS);
    }
    
    /**
     * Unloads the Settings mask.
     * @throws IOException
     */
    public final void unloadSettings() throws IOException {
        this.activityManager.delMask(MaskPath.SETTINGS);
    }
    
    /**
     * Loads the Accounting mask.
     * @throws IOException
     */
    public final void loadAccounting() throws IOException {
        this.activityManager.setMask(MaskPath.ACCOUNTING);
    }
    
    /**
     * Unloads the Accounting mask.
     * @throws IOException
     */
    public final void unloadAccounting() throws IOException {
        this.activityManager.delMask(MaskPath.ACCOUNTING);
    }
    
    /**
     * Loads the About mask.
     * @throws IOException
     */
    public final void loadAbout() throws IOException {
        this.activityManager.setMask(MaskPath.ABOUT);
    }
    
    /**
     * Unloads the Accounting mask.
     * @throws IOException
     */
    public final void unloadAbout() throws IOException {
        this.activityManager.delMask(MaskPath.ABOUT);
    }
    
    /**
     * Loads the About mask.
     * @throws IOException
     */
    public final void loadActivity() throws IOException {
        this.activityManager.setMask(MaskPath.ACTIVITY);
    }
    
    /**
     * Unloads the Accounting mask.
     * @throws IOException
     */
    public final void unloadActivity() throws IOException {
        this.activityManager.delMask(MaskPath.ACTIVITY);
    }
    
    private void createActivityLog(ProgramUser programUser, ActivityType activityType) {
        // Create an ActivityLog.
        ActivityLog activityLog = new ActivityLog();
        activityLog.setCreation(new Date());
        activityLog.setActivityType(activityType);
        activityLog.setProgramUser(programUser);
        System.out.println("activityType: " + activityType);
        System.out.println("activityLog: " + activityLog);

        // Persist the ActivityLog.
        this.service.createActivityLog(activityLog);
    }
    
    @Override
    public final void initialize(final URL url, final ResourceBundle rb) {
        System.out.println("load SceneController.initialize(...)");
        
        // Check if System user exists.
        if (this.service.checkUsername(Main.getSystemUser().getUsername()) == null) {
            // Create System user.
            this.service.createProgramUser(Main.getSystemUser());
        }
        
        // Initialize activity.
        this.activityManager = new ActiveMenuManager(activity, container);
        
        // Load Login mask.
        try {
            loadLogin();
        } catch (IOException ex) {
            // TODO
            Logger.getLogger(SceneController.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
